home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / tex / tgrind.zip / VGRINDEF.C < prev    next >
C/C++ Source or Header  |  1990-05-23  |  6KB  |  296 lines

  1. #ifndef lint
  2. static char sccsid[] = "@(#)vgrindefs.c    4.3 (Berkeley) 12/11/84";
  3. #endif
  4.  
  5. /* Copyright (c) 1979 Regents of the University of California */
  6.  
  7. #define    BUFSIZ    1024
  8. #define MAXHOP    32    /* max number of tc= indirections */
  9.  
  10. #include <ctype.h>
  11. /*
  12.  * grindcap - routines for dealing with the language definitions data base
  13.  *    (code stolen almost totally from termcap)
  14.  *
  15.  * BUG:        Should use a "last" pointer in tbuf, so that searching
  16.  *        for capabilities alphabetically would not be a n**2/2
  17.  *        process when large numbers of capabilities are given.
  18.  * Note:    If we add a last pointer now we will screw up the
  19.  *        tc capability. We really should compile termcap.
  20.  *
  21.  * Essentially all the work here is scanning and decoding escapes
  22.  * in string capabilities.  We don't use stdio because the editor
  23.  * doesn't, and because living w/o it is not hard.
  24.  */
  25.  
  26. static    char *tbuf;
  27. static    char *filename;
  28. static    int hopcount;    /* detect infinite loops in termcap, init 0 */
  29. char    *tskip();
  30. char    *tgetstr();
  31. char    *tdecode();
  32. char    *getenv();
  33.  
  34. /*
  35.  * Get an entry for terminal name in buffer bp,
  36.  * from the termcap file.  Parse is very rudimentary;
  37.  * we just notice escaped newlines.
  38.  */
  39. tgetent(bp, name, file)
  40.     char *bp, *name, *file;
  41. {
  42.     register char *cp;
  43.     register int c;
  44.     register int i = 0, cnt = 0;
  45.     char ibuf[BUFSIZ];
  46.     char *cp2;
  47.     int tf;
  48.  
  49.     tbuf = bp;
  50.     tf = 0;
  51.     filename = file;
  52.     tf = open(filename, 0);
  53.     if (tf < 0)
  54.         return (-1);
  55.     for (;;) {
  56.         cp = bp;
  57.         for (;;) {
  58.             if (i == cnt) {
  59.                 cnt = read(tf, ibuf, BUFSIZ);
  60.                 if (cnt <= 0) {
  61.                     close(tf);
  62.                     return (0);
  63.                 }
  64.                 i = 0;
  65.             }
  66.             c = ibuf[i++];
  67.             if (c == '\n') {
  68.                 if (cp > bp && cp[-1] == '\\'){
  69.                     cp--;
  70.                     continue;
  71.                 }
  72.                 break;
  73.             }
  74.             if (cp >= bp+BUFSIZ) {
  75.                 write(2,"Vgrind entry too long\n", 23);
  76.                 break;
  77.             } else
  78.                 *cp++ = c;
  79.         }
  80.         *cp = 0;
  81.  
  82.         /*
  83.          * The real work for the match.
  84.          */
  85.         if (tnamatch(name)) {
  86.             close(tf);
  87.             return(tnchktc());
  88.         }
  89.     }
  90. }
  91.  
  92. /*
  93.  * tnchktc: check the last entry, see if it's tc=xxx. If so,
  94.  * recursively find xxx and append that entry (minus the names)
  95.  * to take the place of the tc=xxx entry. This allows termcap
  96.  * entries to say "like an HP2621 but doesn't turn on the labels".
  97.  * Note that this works because of the left to right scan.
  98.  */
  99. tnchktc()
  100. {
  101.     register char *p, *q;
  102.     char tcname[16];    /* name of similar terminal */
  103.     char tcbuf[BUFSIZ];
  104.     char *holdtbuf = tbuf;
  105.     int l;
  106.  
  107.     p = tbuf + strlen(tbuf) - 2;    /* before the last colon */
  108.     while (*--p != ':')
  109.         if (p<tbuf) {
  110.             write(2, "Bad vgrind entry\n", 18);
  111.             return (0);
  112.         }
  113.     p++;
  114.     /* p now points to beginning of last field */
  115.     if (p[0] != 't' || p[1] != 'c')
  116.         return(1);
  117.     strcpy(tcname,p+3);
  118.     q = tcname;
  119.     while (q && *q != ':')
  120.         q++;
  121.     *q = 0;
  122.     if (++hopcount > MAXHOP) {
  123.         write(2, "Infinite tc= loop\n", 18);
  124.         return (0);
  125.     }
  126.     if (tgetent(tcbuf, tcname, filename) != 1)
  127.         return(0);
  128.     for (q=tcbuf; *q != ':'; q++)
  129.         ;
  130.     l = p - holdtbuf + strlen(q);
  131.     if (l > BUFSIZ) {
  132.         write(2, "Vgrind entry too long\n", 23);
  133.         q[BUFSIZ - (p-tbuf)] = 0;
  134.     }
  135.     strcpy(p, q+1);
  136.     tbuf = holdtbuf;
  137.     return(1);
  138. }
  139.  
  140. /*
  141.  * Tnamatch deals with name matching.  The first field of the termcap
  142.  * entry is a sequence of names separated by |'s, so we compare
  143.  * against each such name.  The normal : terminator after the last
  144.  * name (before the first field) stops us.
  145.  */
  146. tnamatch(np)
  147.     char *np;
  148. {
  149.     register char *Np, *Bp;
  150.  
  151.     Bp = tbuf;
  152.     if (*Bp == '#')
  153.         return(0);
  154.     for (;;) {
  155.         for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
  156.             continue;
  157.         if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
  158.             return (1);
  159.         while (*Bp && *Bp != ':' && *Bp != '|')
  160.             Bp++;
  161.         if (*Bp == 0 || *Bp == ':')
  162.             return (0);
  163.         Bp++;
  164.     }
  165. }
  166.  
  167. /*
  168.  * Skip to the next field.  Notice that this is very dumb, not
  169.  * knowing about \: escapes or any such.  If necessary, :'s can be put
  170.  * into the termcap file in octal.
  171.  */
  172. static char *
  173. tskip(bp)
  174.     register char *bp;
  175. {
  176.  
  177.     while (*bp && *bp != ':')
  178.         bp++;
  179.     if (*bp == ':')
  180.         bp++;
  181.     return (bp);
  182. }
  183.  
  184. /*
  185.  * Return the (numeric) option id.
  186.  * Numeric options look like
  187.  *    li#80
  188.  * i.e. the option string is separated from the numeric value by
  189.  * a # character.  If the option is not found we return -1.
  190.  * Note that we handle octal numbers beginning with 0.
  191.  */
  192. tgetnum(id)
  193.     char *id;
  194. {
  195.     register int i, base;
  196.     register char *bp = tbuf;
  197.  
  198.     for (;;) {
  199.         bp = tskip(bp);
  200.         if (*bp == 0)
  201.             return (-1);
  202.         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
  203.             continue;
  204.         if (*bp == '@')
  205.             return(-1);
  206.         if (*bp != '#')
  207.             continue;
  208.         bp++;
  209.         base = 10;
  210.         if (*bp == '0')
  211.             base = 8;
  212.         i = 0;
  213.         while (isdigit(*bp))
  214.             i *= base, i += *bp++ - '0';
  215.         return (i);
  216.     }
  217. }
  218.  
  219. /*
  220.  * Handle a flag option.
  221.  * Flag options are given "naked", i.e. followed by a : or the end
  222.  * of the buffer.  Return 1 if we find the option, or 0 if it is
  223.  * not given.
  224.  */
  225. tgetflag(id)
  226.     char *id;
  227. {
  228.     register char *bp = tbuf;
  229.  
  230.     for (;;) {
  231.         bp = tskip(bp);
  232.         if (!*bp)
  233.             return (0);
  234.         if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
  235.             if (!*bp || *bp == ':')
  236.                 return (1);
  237.             else if (*bp == '@')
  238.                 return(0);
  239.         }
  240.     }
  241. }
  242.  
  243. /*
  244.  * Get a string valued option.
  245.  * These are given as
  246.  *    cl=^Z
  247.  * Much decoding is done on the strings, and the strings are
  248.  * placed in area, which is a ref parameter which is updated.
  249.  * No checking on area overflow.
  250.  */
  251. char *
  252. tgetstr(id, area)
  253.     char *id, **area;
  254. {
  255.     register char *bp = tbuf;
  256.  
  257.     for (;;) {
  258.         bp = tskip(bp);
  259.         if (!*bp)
  260.             return (0);
  261.         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
  262.             continue;
  263.         if (*bp == '@')
  264.             return(0);
  265.         if (*bp != '=')
  266.             continue;
  267.         bp++;
  268.         return (tdecode(bp, area));
  269.     }
  270. }
  271.  
  272. /*
  273.  * Tdecode does the grung work to decode the
  274.  * string capability escapes.
  275.  */
  276. static char *
  277. tdecode(str, area)
  278.     register char *str;
  279.     char **area;
  280. {
  281.     register char *cp;
  282.     register int c;
  283.     int i;
  284.  
  285.     cp = *area;
  286.     while (c = *str++) {
  287.         if (c == ':' && *(cp-1) != '\\')
  288.         break;
  289.         *cp++ = c;
  290.     }
  291.     *cp++ = 0;
  292.     str = *area;
  293.     *area = cp;
  294.     return (str);
  295. }
  296.